package com.york.tinyrpc.protoss.fault.tolerant;

import com.york.tinyrpc.protoss.constant.TinyRpcConstants;
import com.york.tinyrpc.protoss.loadbalancer.LoadBalancer;
import com.york.tinyrpc.protoss.model.ServiceMetaInfo;
import com.york.tinyrpc.protoss.model.TinyRpcRequest;
import com.york.tinyrpc.protoss.model.TinyRpcResponse;
import com.york.tinyrpc.protoss.server.tcp.VertxTcpClient;

import java.util.List;
import java.util.Map;

/**
 * 故障转移模式容错策略
 * context里存入可选服务列表（剔除当前执行节点）
 */
public class FailOverTolerantStrategy implements TolerantStrategy {

    @Override
    public TinyRpcResponse doTolerant(Map<String, Object> context, Exception e) {

        // 指定有效的服务列表和被二次选中的服务
        List<ServiceMetaInfo> validServiceMetaInfos;
        ServiceMetaInfo selectedServiceMetaInfo;
        TinyRpcRequest request;
        try {
            // 获取有效服务列表，可供转移，转移的时候就不需要重试了
            validServiceMetaInfos =
                    (List<ServiceMetaInfo>) context.get(TinyRpcConstants.VALID_SERVICE_META_INFOS);
            request =
                    (TinyRpcRequest) context.get(TinyRpcConstants.TINY_RPC_REQUEST);
            if (validServiceMetaInfos.size() == 1) {
                // 不需要负载均衡了，直接让他去执行
                selectedServiceMetaInfo = validServiceMetaInfos.get(0);
                return VertxTcpClient.doRequest(request, selectedServiceMetaInfo);
            }

            // 获取负载均衡器
            LoadBalancer targetLoadBalancer =
                    (LoadBalancer) context.get(TinyRpcConstants.TARGET_LOAD_BALANCER);

            Map<String, Object> requestParams =
                    (Map<String, Object>) context.get(TinyRpcConstants.LOAD_BALANCE_PARAMS);

            selectedServiceMetaInfo =
                    targetLoadBalancer.getTargetService(requestParams, validServiceMetaInfos);
        } catch (Exception ex) {
            throw new RuntimeException("类型转换异常");
        }
        return VertxTcpClient.doRequest(request, selectedServiceMetaInfo);
    }
}
